package com.zxy.ziems.server.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zxy.btp.common.exception.ConditionException;
import com.zxy.btp.common.response.PageResult;
import com.zxy.ziems.server.convert.DeptConvert;
import com.zxy.ziems.server.domain.Dept;
import com.zxy.ziems.server.domain.User;
import com.zxy.ziems.server.dto.DeptDto;
import com.zxy.ziems.server.dto.DeptQueryDto;
import com.zxy.ziems.server.dto.DeptTreeNode;
import com.zxy.ziems.server.dto.ResourceTree;
import com.zxy.ziems.server.mapper.DeptMapper;
import com.zxy.ziems.server.service.DeptService;
import com.zxy.ziems.server.service.UserService;
import com.zxy.ziems.server.vo.DeptVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @DATE 2021/3/10
 */
@Service
@Slf4j
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {

    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private UserService userService;

    private static final String BASE_DEPT_ID = "-1";


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(DeptDto deptDto) {
        //校验编码
        checkCodeAndName(deptDto);
        String deptId = deptDto.getDeptId();
        Dept dept = DeptConvert.INSTANCE.deptDtoToDept(deptDto);
        if (StrUtil.isEmpty(deptId)) {
            deptMapper.insert(dept);
        }else {
            deptMapper.updateById(dept);
        }

    }

    private void checkCodeAndName(DeptDto deptDto) {
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Dept::getDeptCode, deptDto.getDeptCode())
                .notIn(StrUtil.isNotEmpty(deptDto.getDeptId()),Dept::getDeptId,deptDto.getDeptId());
        List<Dept> dataList = deptMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(dataList)) {
            throw new ConditionException("部门编码已存在");
        }
        queryWrapper.clear();
        queryWrapper.lambda().eq(Dept::getDeptName, deptDto.getDeptName())
                .notIn(StrUtil.isNotEmpty(deptDto.getDeptId()),Dept::getDeptId,deptDto.getDeptId());
        List<Dept> list = deptMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            throw new ConditionException("部门名称已存在");
        }
    }

    @Override
    @Transactional(readOnly = true)
    public DeptVo detail(String deptId) {
        Dept dept = deptMapper.selectById(deptId);
        if (ObjectUtil.isEmpty(dept)) {
            return null;
        }
        DeptVo deptVo = DeptConvert.INSTANCE.deptToDeptVo(dept);
        //查询上级部门名称
        Dept parentDept = deptMapper.selectById(dept.getParentId());
        if (ObjectUtil.isNotEmpty(parentDept)) {
            deptVo.setParentDeptName(parentDept.getDeptName());
        }
        //查询负责人名称
        User bossUser = userService.getById(dept.getBossId());
        if (ObjectUtil.isNotEmpty(bossUser)) {
            deptVo.setBossName(bossUser.getUserName());
        }
        return deptVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String deptId) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        List<User> userList = userService.list(queryWrapper.lambda().eq(User::getOrgId, deptId));
        if (CollectionUtil.isNotEmpty(userList)) {
            throw new ConditionException("请先移除该组织下的用户");
        }

        QueryWrapper<Dept> query = new QueryWrapper<>();
        query.lambda().eq(Dept::getParentId,deptId);
        List<Dept> companyDeptList = deptMapper.selectList(query);
        if (CollectionUtil.isNotEmpty(companyDeptList)) {
            throw new ConditionException("请先移除该组织下的子组织");
        }
        deptMapper.deleteById(deptId);
    }

    @Override
    @Transactional(readOnly = true)
    public PageResult<DeptVo> pageList(DeptQueryDto deptQueryDto) {
        Page<Dept> companyDeptPage = deptMapper.selectPage(new Page<>(deptQueryDto.getPageNo(), deptQueryDto.getPageSize()),
                new QueryWrapper<Dept>().lambda()
                        .like(StrUtil.isNotEmpty(deptQueryDto.getDeptName()), Dept::getDeptName, deptQueryDto.getDeptName())
                        .eq(StrUtil.isNotEmpty(deptQueryDto.getParentDeptId()), Dept::getParentId, deptQueryDto.getParentDeptId())
                        .orderByDesc(Dept::getUpdateTime));
        List<Dept> records = companyDeptPage.getRecords();
        if (records.size() == 0) {
            return null;
        }
        List<String> parentIds = records.stream().map(Dept::getParentId).distinct().collect(Collectors.toList());
        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(Dept::getDeptId, parentIds);
        List<Dept> parentDeptList = deptMapper.selectList(queryWrapper);
        List<DeptVo> deptVoList = DeptConvert.INSTANCE.deptListToDeptVoList(records);
        //获取所有相关userID
        List<String> bossUserIds = records.stream().filter(N -> StrUtil.isNotBlank(N.getBossId())).map(M -> M.getBossId()).collect(Collectors.toList());
        //获取所用用户信息
        if (ObjectUtil.isNotEmpty(bossUserIds)) {
            List<User> users = userService.listByIds(bossUserIds);
            Map<String, String> map = users.stream().collect(Collectors.toMap(User::getUserId, User::getUserName));
            for (DeptVo deptVo : deptVoList) {
                String userName = map.get(deptVo.getBossId());
                //负责人名称赋值
               deptVo.setBossName(userName);
            }
        }

        //查询所有yoghurt信息
        Map<String, String> deptMap = parentDeptList.stream().collect(Collectors.toMap(Dept::getDeptId, Dept::getDeptName));
        deptVoList.stream().forEach(deptVo -> {
            if (deptVo.getParentId().equals("-1")) {
                deptVo.setParentDeptName("/");
            } else {
                deptVo.setParentDeptName(deptMap.get(deptVo.getParentId()));
            }
        });
        return new PageResult<>(companyDeptPage.getTotal(), deptVoList);
    }


    /**
     * 返回部门树
     *
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public DeptTreeNode tree() {
        DeptTreeNode deptTreeNode = new DeptTreeNode("-1", "集团",0);
        List<DeptTreeNode> root = new ArrayList<>();
        Map<String, DeptTreeNode> nodeMap = new HashMap<>();

        QueryWrapper<Dept> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(Dept::getSortNo);
        queryWrapper.lambda().orderByDesc(Dept::getUpdateTime);
        List<Dept> deptList = deptMapper.selectList(queryWrapper);
        deptList.stream().forEach(x -> {
            DeptTreeNode treeNode = new DeptTreeNode(x.getDeptId(), x.getDeptName(),x.getSortNo());
            nodeMap.put(x.getDeptId(), treeNode);
            if ("-1".equals(x.getParentId())) {
                root.add(treeNode);
            }

        });
        deptList.stream().forEach(x -> {
            DeptTreeNode node = nodeMap.get(x.getDeptId());
            DeptTreeNode parent = nodeMap.get(x.getParentId());
            if (parent != null) {
                parent.getChildren().add(node);
            }
        });
        //树排序
        for (DeptTreeNode treeNode : root) {
            List<DeptTreeNode> children = treeNode.getChildren();
            if (null == children || children.isEmpty()){
                continue;
            }
            children.sort(Comparator.comparingInt(DeptTreeNode::getSortNo));
        }

        deptTreeNode.getChildren().addAll(root);
        return deptTreeNode;
    }
}
